﻿using System.ComponentModel;
using System.Runtime.Serialization;

using SharpGL.Enumerations;

namespace SharpGL.OpenGLAttributes
{
    /// <summary>
    /// The OpenGLAttributes is the base for groups of opengl attributes.
    /// </summary>
    [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
    [DataContract(/*IsReference = true, */Name = "OpenGLAttributes", Namespace = "SharpGL.SceneGraph")]
    public abstract class OpenGLAttributes : INotifyPropertyChanged
    {
        #region Private Consts

        private static readonly AttributeMask attributeMask = AttributeMask.None;
        
        #endregion Private Consts

        #region Private Fields

        /// <summary>
        /// The attribute flags for the group.
        /// </summary>
        [IgnoreDataMember()]
        private AttributeMask attributeFlags;

        #endregion PrivateFields

        #region Private Methods

        [OnDeserialized]
        private void OnDeserialized(StreamingContext ctx)
        {
            OnDeserialized();
        }

        [OnDeserializing]
        private void OnDeserializing(StreamingContext ctx)
        {
            OnDeserializing();
        }

        #endregion Private Methods

        #region Protected Methods

        /// <summary>
        /// Call this function to do the PropertyChanged event.
        /// </summary>
        protected void NotifyPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        protected virtual void OnDeserialized()
        {
        }

        protected virtual void OnDeserializing()
        {
            attributeFlags = attributeMask;
        }

        #endregion Protected Methods

        #region Public Constructors

        public OpenGLAttributes()
        {
            attributeFlags = attributeMask;
        }

        #endregion Public Cobstructors

        #region Public Methods

        /// <summary>
        /// Returns true if any attributes are set.
        /// </summary>
        /// <returns>True if any attributes are set</returns>
        public abstract bool AreAnyAttributesSet();

        /// <summary>
        /// Reset all attributes to unset state.
        /// </summary>
        public abstract void ResetAllAttributes();

        /// <summary>
        /// Sets the attributes.
        /// </summary>
        /// <param name="gl">The OpenGL instance.</param>
        public abstract void SetAttributes(OpenGL gl);

        #endregion Public Methods

        #region Public Events

        [Description("Called when properties of OpenGL attributes has been changed."), Category("SharpGL")]
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion Public Events

        #region Public Properties

        /// <summary>
        /// Gets the attribute flags.
        /// todo use get only, xmlignore and don't store them - return them on the fly.
        /// </summary>
        public virtual AttributeMask AttributeFlags
        {
            get { return attributeFlags; }
            protected set
            {
                attributeFlags = value;
                
                NotifyPropertyChanged("AttributeFlags");
            }
        }

        #endregion Public Properties
    }
}
